﻿using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

public class ScrollItemReorder : MonoBehaviour
, IInitializePotentialDragHandler, IBeginDragHandler, IEndDragHandler, IDragHandler
, IScrollHandler
{

    public ScrollRect m_ScrollRect;
    public string m_DragNodeName = "dragItem";

    public RectTransform m_ForwardScrollTrans; //把条目拖到这个区域, 自动往前滑动列表
    public RectTransform m_BackwordScrollTrans; //把条目拖到这个区域, 自动往后滑动列表

    private Dictionary<Transform, Transform> m_SlotItemDict = new Dictionary<Transform, Transform>(); //slot -> 拖拽条目

    private RectTransform m_DragItemTrans; //当前在拖动的条目
    private RectTransform m_EmptySlot; //没有条目的空槽

    private Camera m_PressCamera;
    private Vector2 m_LastDragPosition;

    private int m_AutoScrollDir = 0;
    private float m_AutoScrollSpeed = 0.0005f; //根据条目数量, 适当的调整速度, 比如: 0.1f / count

    public float autoScrollSpeed
    {
        get { return m_AutoScrollSpeed; }
        set { m_AutoScrollSpeed = value; }
    }

    public void SetSlotItem(Transform slotTrans, Transform itemTrans)
    {
        m_SlotItemDict[slotTrans] = itemTrans;
    }

    public void ClearSlotItemDict()
    {
        m_SlotItemDict.Clear();
    }

    public void OnInitializePotentialDrag(PointerEventData eventData)
    {
        if (eventData.button != PointerEventData.InputButton.Left) return;

        m_ScrollRect.OnInitializePotentialDrag(eventData);
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        if (eventData.button != PointerEventData.InputButton.Left) return;

        if (!IsDragItem(eventData))
            m_ScrollRect.OnBeginDrag(eventData);
    }

    private bool IsDragItem(PointerEventData eventData)
    {
        if (null != m_DragItemTrans) return false;
        if (null == eventData.rawPointerPress) return false;
        if (eventData.rawPointerPress.name != m_DragNodeName) return false;

        var dragNodeTrans = (RectTransform)eventData.rawPointerPress.transform;
        m_DragItemTrans = dragNodeTrans;
        m_EmptySlot = (RectTransform)m_DragItemTrans.parent;
        m_PressCamera = eventData.pressEventCamera;

        Vector2 localPos;
        RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out localPos);
        m_LastDragPosition = localPos;

        m_DragItemTrans.SetParent(m_ScrollRect.transform);
        m_DragItemTrans.SetSiblingIndex(1);
        return true;
    }

    public void OnDrag(PointerEventData eventData)
    {
        if (eventData.button != PointerEventData.InputButton.Left) return;

        if (null != m_DragItemTrans)
        {
            Vector2 localPos;
            RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)transform, eventData.position, eventData.pressEventCamera, out localPos);
            Vector2 delta = localPos - m_LastDragPosition;
            m_LastDragPosition = localPos;

            Vector2 anchoredPos = m_DragItemTrans.anchoredPosition;
            anchoredPos.y += delta.y;
            m_DragItemTrans.anchoredPosition = anchoredPos;

            if (CheckSwap())
                return;

            CheckAutoScroll();
        }
        else
        {
            m_ScrollRect.OnDrag(eventData);
        }
    }

    private bool CheckSwap()
    {
        foreach (var entry in m_SlotItemDict)
        {
            var destSlotTrans = (RectTransform)entry.Key;
            if (destSlotTrans == m_EmptySlot) continue;

            Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(m_PressCamera, m_DragItemTrans.position);
            RectTransformUtility.ScreenPointToLocalPointInRectangle(destSlotTrans, screenPos, m_PressCamera, out var localPos);
            //Debug.Log($"CheckSwap: {localPoint}");
            if (Mathf.Abs(localPos.y) < 50)
            {
                //emptySlot切换:
                //pointer悬停处的条目放入旧emptySlot
                var destItemTrans = (RectTransform)entry.Value;
                destItemTrans.SetParent(m_EmptySlot, false);
                destItemTrans.anchoredPosition = Vector2.zero;
                m_SlotItemDict[m_EmptySlot] = destItemTrans;
                //pointer悬停处的slot成为新emptySlot
                m_SlotItemDict[destSlotTrans] = m_DragItemTrans;
                m_EmptySlot = destSlotTrans;
                return true;
            }
        }
        return false;
    }

    private void CheckAutoScroll()
    {
        m_AutoScrollDir = 0;

        Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(m_PressCamera, m_DragItemTrans.position);
        if (null != m_ForwardScrollTrans)
        {
            bool result = RectTransformUtility.ScreenPointToLocalPointInRectangle(m_ForwardScrollTrans, screenPos, m_PressCamera, out var localPos);
            if (Mathf.Abs(localPos.y) < 15)
                m_AutoScrollDir = 1; //vertical-topDown列表, 最前面是1, 所以往前滑动要增加percent

            Debug.Log($"CheckAutoScroll: b:{result}, dir:{m_AutoScrollDir}, point:{localPos}");
        }

        if (null != m_BackwordScrollTrans)
        {
            bool result = RectTransformUtility.ScreenPointToLocalPointInRectangle(m_BackwordScrollTrans, screenPos, m_PressCamera, out var localPos);
            if (Mathf.Abs(localPos.y) < 15)
                m_AutoScrollDir = -1; //vertical-topDown列表, 最后面是0, 所以往后滑动要减少percent

            Debug.Log($"CheckAutoScroll: b:{result}, dir:{m_AutoScrollDir}, point:{localPos}");
        }
    }

    void Update()
    {
        if (m_AutoScrollDir > 0) //scrollOffset增大
        {
            float percent = m_ScrollRect.verticalNormalizedPosition;
            if (percent >= 1)
            {
                m_AutoScrollDir = 0;
            }
            else
            {
                percent += m_AutoScrollSpeed * m_AutoScrollDir;
                if (percent >= 1)
                {
                    m_AutoScrollDir = 0;
                    percent = 1;
                }
                m_ScrollRect.verticalNormalizedPosition = percent;
                CheckSwap();
            }
        }
        else if (m_AutoScrollDir < 0) //scrollOffset减小
        {
            float percent = m_ScrollRect.verticalNormalizedPosition;
            if (percent <= 0)
            {
                m_AutoScrollDir = 0;
            }
            else
            {
                percent += m_AutoScrollSpeed * m_AutoScrollDir;
                if (percent <= 0)
                {
                    m_AutoScrollDir = 0;
                    percent = 0;
                }
                m_ScrollRect.verticalNormalizedPosition = percent;
                CheckSwap();
            }
        }
    }


    public void OnEndDrag(PointerEventData eventData)
    {
        if (eventData.button != PointerEventData.InputButton.Left) return;

        if (null != m_DragItemTrans)
        {
            m_DragItemTrans.SetParent(m_EmptySlot, false);
            m_DragItemTrans.anchoredPosition = Vector2.zero;

            m_DragItemTrans = null;
            m_DragItemTrans = null;
            m_EmptySlot = null;
            m_AutoScrollDir = 0;
            m_PressCamera = null;
        }
        else
        {
            m_ScrollRect.OnEndDrag(eventData);
        }
    }

    public void OnScroll(PointerEventData eventData)
    {
        if (null == m_DragItemTrans)
            m_ScrollRect.OnScroll(eventData);
    }

}
